package com.example.user.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.example.user.service.UserService;

import entity.ServerResponseBody;
import mapper.UserMapper;
import org.apache.shiro.crypto.hash.Md5Hash;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import pojo.Comment;
import pojo.User;
import pojo.UserInfo;
import pojo.Vehicle;
import sun.java2d.pipe.SpanShapeRenderer;
import util.JwtUtil;
import vo.CommentVo;
import vo.LoginVo;
import vo.RegisterVo;
import vo.UserInfoVo;

import javax.servlet.http.HttpServletResponse;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

/**
 * @BelongsProject: gxcwhd
 * @BelongsPackage: com.example.user.service.impl
 * @Author: huan
 * @CreateTime: 2020-08-14 10:08
 * @Description:   用户操作业务逻辑类
 */
@Service
@Transactional
public class UserServiceImpl implements UserService {

    //用户数据操作类
    @Autowired
    private UserMapper userMapper;

    //redis操作类
    @Autowired
    private RedisTemplate<String, String> redisTemplate;

    //盐
    private final String SALT = "huan";

    //散列次数
    private final Integer HASHITERATIONS = 5;


    /**
     * fastJSON
     *
     * // json转换成java对象
     * Myclass myclass = JSONObject.parseObject(jsonStr , Myclass.class);
     *
     * //java对象转换成json
     * String jsonObject = JSONObject.toJSONString(myclass);
     */

    /**
     * 用户注册
     * @param registerVo 用户注册信息
     * @return
     */
    @Override
    @Transactional
    public Integer userRegister(RegisterVo registerVo) {

        if(userMapper.queryByUsernameAndPhone(registerVo) != null){
            return 30000;
        }
        User user = new User();
        String userId = UUID.randomUUID().toString().replaceAll("-","");
        String userInfoId = UUID.randomUUID().toString().replaceAll("-","");
        user.setUserId(userId);
        user.setUserInfoId(userInfoId);
        user.setUsername(registerVo.getUsername());

        // shiro 对密码进行 MD5 加密
        Md5Hash md5 = new Md5Hash(registerVo.getPassword(),SALT,HASHITERATIONS);
        registerVo.setPassword(md5.toString());
        user.setPassword(registerVo.getPassword());

        user.setCreateTime(new SimpleDateFormat("yyyy-MM-dd hh:mm:ss").format(new Date()));

        if(registerVo.getRoleName().equals("LESSOR")){
            user.setRoleId("1");
        }else if(registerVo.getRoleName().equals("TENANT")){
            user.setRoleId("2");
        }

        user.setPhone(registerVo.getPhone());
        user.setUserAvatar("http://127.0.0.1:5500/Airparking/img/滑稽鱼.png");

        Integer i1 = userMapper.addUserInfo(user);

        //将用户信息存入 Redis
        redisTemplate.opsForValue().set(user.getUserId(), JSONObject.toJSONString(user));

        return userMapper.addUser(user);
    }

    /**
     * 用户登录
     * @param loginVo
     * @param response
     * @return
     */
    @Override
    @Transactional(readOnly = true)
    public ServerResponseBody userLogin(LoginVo loginVo, HttpServletResponse response) {

        // shiro 对密码进行 MD5 加密
        Md5Hash md5 = new Md5Hash(loginVo.getPassword(),SALT,HASHITERATIONS);
        loginVo.setPassword(md5.toString());

        User userInfo = userMapper.userLogin(loginVo);


        if(userInfo == null){
            return ServerResponseBody.fail().msg("用户名或密码错误");
        }else{
            try {
                return ServerResponseBody.success(JwtUtil.createToken(userInfo)).msg("登录成功");
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return null;
    }

    /**
     * 得到用户信息
     * @param userId
     * @return
     */
    @Override
    @Transactional(readOnly = true)
    public ServerResponseBody getUserInfo(String userId) {

        //先去 Redis查找有没有该用户的信息，如果有，直接返回Redis的 对象的 JSON字符串，然后用 fastjson 转成对象
        String userJSON = redisTemplate.opsForValue().get(userId);

        if (userJSON != null) {
            User user = JSONObject.parseObject(userJSON, User.class);
            System.err.println("直接在 redis 中查询");
            return ServerResponseBody.success(user);
        }

        //如果 Redis 中没有则在 mysql 中查询，再存入 Redis
        User user = userMapper.getUserInfoById(userId);

        //将用户信息存入 Redis
        redisTemplate.opsForValue().set(user.getUserId(), JSONObject.toJSONString(user));

        if(user == null){
            return ServerResponseBody.fail();
        }

        return ServerResponseBody.success(user);
    }


    /**
     * 个人中心，得到用户详情信息
     * @param userId
     * @return
     */
    @Override
    @Transactional(readOnly = true)
    public ServerResponseBody getUserDetailInfo(String userId) {

        //先去 Redis查找有没有该用户的信息，如果有，直接返回Redis的 对象的 JSON字符串，然后用 fastjson 转成对象
        String userInfoJSON = redisTemplate.opsForValue().get("userInfo-" + userId);

        if (userInfoJSON != null) {
            UserInfoVo userInfo = JSONObject.parseObject(userInfoJSON, UserInfoVo.class);
            System.err.println("直接在 redis 中查询");
            return ServerResponseBody.success(userInfo);
        }

        //如果 Redis 中没有则在 mysql 中查询，再存入 Redis
        UserInfoVo userInfo = userMapper.getUserDetailInfo(userId);

        //将用户信息存入 Redis
        redisTemplate.opsForValue().set("userInfo-" + userId, JSONObject.toJSONString(userInfo));

        if(userInfo == null){
            return ServerResponseBody.fail();
        }

        return ServerResponseBody.success(userInfo);
    }

    /**
     * 修改密码
     * @param userId
     * @param loginVo
     * @return
     */
    @Override
    @Transactional
    public ServerResponseBody changePassword(String userId, LoginVo loginVo) {

        if(!loginVo.getNewPassword().equals(loginVo.getConfirmPassword())){
            return ServerResponseBody.fail().code(500);
        }

        User user = userMapper.getUserInfoById(userId);

        // shiro 对密码进行 MD5 加密
        Md5Hash md5 = new Md5Hash(loginVo.getOldPassword(),SALT,HASHITERATIONS);
        loginVo.setOldPassword(md5.toString());

        md5 = new Md5Hash(loginVo.getNewPassword(),SALT,HASHITERATIONS);
        loginVo.setNewPassword(md5.toString());

        if(!user.getPassword().equals(loginVo.getOldPassword())){
            return ServerResponseBody.fail().code(300);
        }

        //修改 mysql中的密码后，将修改后的用户信息存入 Redis 中
        Integer i = userMapper.changePassword(userId,loginVo);

        if(i == 1){
            //将用户信息重新存入 redis
            User u = userMapper.getUserInfoById(userId);
            redisTemplate.opsForValue().set(userId,JSONObject.toJSONString(u));
            return ServerResponseBody.success(null);
        }

        return ServerResponseBody.fail();
    }

    /**
     * 得到车辆信息
     * @param userId
     * @return
     */
    @Override
    @Transactional(readOnly = true)
    public ServerResponseBody getUserVehicleInfo(String userId) {

        Vehicle vehicle = userMapper.getUserVehicleInfo(userId);

        if(vehicle == null){
            return ServerResponseBody.fail();
        }

        return ServerResponseBody.success(vehicle);
    }

    /**
     * 得到该车位的评论信息
     * @param parkingId
     * @return
     */
    @Override
    @Transactional(readOnly = true)
    public ServerResponseBody getParkingComment(String parkingId) {

        System.err.println("进入serviceImpl ---- " + parkingId);
        List<CommentVo> comments = userMapper.getParkingCommentById(parkingId);

        System.err.println(comments.toString());

        if(comments == null){
            return ServerResponseBody.fail();
        }

        return ServerResponseBody.success(comments);
    }

    /**
     * 比较 Redis 中对密码，且常见用户详情信息
     *
     * @param registerVo 用户注册信息
     * @return
     */
    @Override
    @Transactional
    public ServerResponseBody registerUser(RegisterVo registerVo) {

        String phoneCode = redisTemplate.opsForValue().get(registerVo.getPhone());

        //若redis的手机号和验证码和前端传的不一样，不能注册
        if (!registerVo.getPhoneCode().equals(phoneCode)) {

            return ServerResponseBody.fail();
        } else {

            //如果手机号或者用户名已存在，不能注册
            if (userRegister(registerVo) == 30000) {
                return ServerResponseBody.fail().code(30000);
            }

            return ServerResponseBody.success(null);
        }
    }

    /**
     * 得到评论的回复评论信息
     * @param commentId
     * @return
     */
    @Override
    @Transactional(readOnly = true)
    public ServerResponseBody getChildrenComment(String commentId) {
         List<CommentVo> childrenComments = userMapper.getChildrenComment(commentId);

         if(childrenComments == null){
            return ServerResponseBody.fail().msg("没有回复评论");
         }

         return ServerResponseBody.success(childrenComments);
    }

    /**
     * 增加，修改租客车辆信息
     * @param vehicle
     * @param userId
     * @return
     */
    @Override
    @Transactional
    public ServerResponseBody changeVehicleInfo(Vehicle vehicle,String userId) {

        Vehicle v = userMapper.getUserVehicleInfo(userId);
        vehicle.setUserId(userId);

        //没有查找到车辆信息，则是添加车辆信息
        if(v == null){
            String vehicleId = UUID.randomUUID().toString().replaceAll("-","");

            vehicle.setVehicleId(vehicleId);

            Integer i = userMapper.addVehicleInfo(vehicle);

            if(i == 1){
                return ServerResponseBody.success(null);
            }else{
                return ServerResponseBody.fail();
            }
        }


        //已有车辆信息，修改车辆信息
        Integer i = userMapper.updateVehicleInfo(vehicle);

        if(i == 1){
            return ServerResponseBody.success(null);
        }else{
            return ServerResponseBody.fail();
        }
    }

    /**
     * 修改用户详情信息
     * @param userInfoVo
     * @param userId
     * @return
     */
    @Override
    @Transactional
    public ServerResponseBody changeUserDetailInfo(UserInfoVo userInfoVo, String userId) {

        userInfoVo.setUserId(userId);
        Integer i = userMapper.changeUserDetailInfo(userInfoVo);


        if(i == 1){
            //如果 Redis 中没有则在 mysql 中查询，再存入 Redis
            UserInfoVo userInfo = userMapper.getUserDetailInfo(userId);

            //将用户信息存入 Redis
            redisTemplate.opsForValue().set("userInfo-" + userId, JSONObject.toJSONString(userInfo));

            return ServerResponseBody.success(null);
        }

        return ServerResponseBody.fail();
    }

    /**
     * 得到该用户未读的消息
     * @param userId
     * @return
     */
    @Override
    @Transactional(readOnly = true)
    public ServerResponseBody getNoReadByUserId(String userId) {

        List<CommentVo> noReadMsg = userMapper.getNoReadByUserId(userId);

        if(noReadMsg == null){
            return ServerResponseBody.fail();
        }

        return ServerResponseBody.success(noReadMsg);
    }

    /**
     * 已读消息，将该用户未读的消息全部修改为已读
     * @param userId
     * @return
     */
    @Override
    public ServerResponseBody updateCommentStatus(String userId) {
        Integer i = userMapper.updateCommentStatus(userId);

        if(i > 1){
            return ServerResponseBody.success(null);
        }

        return ServerResponseBody.fail();
    }

    /**
     * 添加消息，回复消息
     * @param userId
     * @return
     */
    @Override
    @Transactional
    public ServerResponseBody replyComment(CommentVo commentVo, String userId) {

        String commentId = UUID.randomUUID().toString().replaceAll("-","");
        commentVo.setSenderId(userId);
        commentVo.setCommentId(commentId);
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        commentVo.setCommentTime(sdf.format(new Date()));

        Integer i = userMapper.replyComment(commentVo);

        if(i == 1){
            return ServerResponseBody.success(null);
        }

        return ServerResponseBody.fail();
    }

}
